<template>
    <div class="ports-achor__wrapper">
        <div id="paper-links-message"></div>
        <div id="portMap"></div>
    </div>
</template>

<script setup>
import { dia, shapes, layout, linkTools } from "jointjs";
import "/node_modules/jointjs/dist/joint.css";

defineOptions({
    name: "Ports",
});

const graph = ref(null);
const paper = ref(null);

// 左端口基本配置
const portDataLeft = reactive({
    label: {
        position: {
            name: 'left'
        },
        markup: [
            {
                tagName: 'text',
                selector: 'label'
            }    
        ]
    },
    attrs: {
        portBody: {
            magnet: true, // 允许端口拖拽连线
            width: 16,
            height: 16,
            x: -8,
            y: -8,
            fill: '#03071E'
        },
        label: {
            text: 'port 1'
        }
    },
    markup: [{
        tagName: 'rect',
        selector: 'portBody'
    }]
})

// 右端口配置
const portDataRight = reactive({
    position: { name: 'right' },
    label: {
        position: {
            name: 'right',
            args: { y: -15, x: 10 }
        },
        markup: [
            {
                tagName: 'text',
                selector: 'label'
            }    
        ]
    },
    attrs: {
        portBody: {
            magnet: true, // 允许端口拖拽连线
            width: 16,
            height: 8,
            x: 0, // 配置x轴值，正数向右移动，负数向左移动，0原点不动
            y: -5, // 配置y轴值，正数向下移动，负数向上移动，0原点不动
            fill: '#03071E'
        },
        label: {
            text: 'port2'
        }
    },
    markup: [{
        tagName: 'rect',
        selector: 'portBody'
    }]
})

// 内端口配置
const portsIn = reactive({
    position: { name: 'left' },
    attrs: {
        portBody: {
            magnet: true,
            r: 10,
            fill: '#023047',
            stroke: '#023047' 
        }
    },
    label: {
        position: { 
            name: 'left',
            args: { y: 1 }
        },
        markup: [{
            tagName: 'text',
            selector: 'label',
            className: 'label-text'
        }]
    },
    markup: [{
        tagName: 'circle',
        selector: 'portBody'
    }]
})
// 外端口配置
const portsOut = reactive({
    position: { name: 'right' },
    attrs: {
        portBody: {
            magnet: true,
            r: 10,
            fill: '#E6A502',
            stroke: '#023047'
        }
    },
    label: {
        position: {
            name: 'right',
            args: { y: 0 }
        },
        markup: [{
            tagName: 'text',
            selector: 'label',
            className: 'label-text'
        }]
    },
    markup: [{
        tagName: 'circle',
        selector: 'portBody'
    }]
})

// 创建图形和页面
function createGraph() {
    graph.value = new dia.Graph({}, { cellNamespace: shapes });
    paper.value = new dia.Paper({
        el: document.getElementById("portMap"),
        model: graph.value,
        width: '100%',
        height: '100%',
        gridSize: 10,
        drawGrid: true,
        background: {
            color: "rgba(0, 255, 0, 0.3)",
        },
        cellViewNamespace: shapes,
        defaultLink: () => new shapes.standard.Link({
            attrs: {
                wrapper: {
                    cursor: 'default'
                }
            }
        }), // 默认链接配置
        linkPinning: false, // 禁止链接拖拽到空白区域
        defaultConnectionPoint: { name: 'boundary' },
        validateConnection: function(cellViewS, magnetS, cellViewT, magnetT, end, linkView) {
            // Prevent loop linking
            return (magnetS !== magnetT);
        }
    });

    // 事件监听
    // Register events
    paper.value.on('link:mouseenter', (linkView) => {
        showLinkTools(linkView);
    });

    paper.value.on('link:mouseleave', (linkView) => {
        linkView.removeTools();
    });

    graph.value.on('change:source change:target', function(link) {
        var sourcePort = link.get('source').port;
        var sourceId = link.get('source').id;
        var targetPort = link.get('target').port;
        var targetId = link.get('target').id;

        var paragraph = document.createElement('p');
        paragraph.innerHTML = [
            '目标端口:<b>' + sourcePort,
            '</b>元素ID <b>' + sourceId,
            '</b>目标端口:<b>' + targetPort,
            '</b>目标端口ID<b>' + targetId + '</b>'
        ].join('');

        appendMessage(paragraph);
    });

    // 端口文本内侧显示
    createLableCenter()
}

function createLableCenter () {
    const rectModel = new shapes.standard.Rectangle({
        position: { x: 100, y: 430 },
        size: { width: 90, height: 90 },
        attrs: {
            body: { fill: '#8ECAE6' }
        },
        ports: {
            // 配置元素端口
            // items: [portDataLeft]
        }
    })
    rectModel.addPort({
        label: {
            position: {
                name: 'right'
            },
            markup: [
                {
                    tagName: 'text',
                    selector: 'label'
                }    
            ]
        },
        attrs: {
            portBody: {
                magnet: true, // 允许端口拖拽连线
                width: 16,
                height: 16,
                x: -8,
                y: -8,
                r: 9,
                fill: '#03071E',
                stroke: 'tomato',
                strokeWidth: 5
            },
            label: {
                text: 'part 3'
            }
        },
        markup: [{
            tagName: 'circle',
            selector: 'portBody'
        }]
    });
    rectModel.addTo(graph.value)
}

// 创建rect矩形元素
function createRect() {
    const rectModel = new shapes.standard.Rectangle({
        position: { x: 100, y: 50 },
        size: { width: 90, height: 90 },
        attrs: {
            body: { fill: '#8ECAE6' }
        },
        ports: {
            // 配置元素端口
            // items: [portDataLeft]
        }
    })
    // 添加一个端口
    // rectModel.addPort(portData)
    // 添加多个端口
    rectModel.addPorts([portDataLeft, portDataLeft])
    rectModel.addTo(graph.value)

    // 创建第二个rect元素
    const rectModelTwo = new shapes.standard.Rectangle({
        position: { x: 400,  y: 50 },
        size: { width: 90, height: 90 },
        attrs: {
            body: { fill: '#8ECAE6' },
            label: {
                text: 'Model',
                fontSize: 16,
                y: -10
            }
        },
        ports: {
            groups: {
                in: portsIn,
                out: portsOut
            }
        }
    })
    rectModelTwo.addPorts([
        {
            group: 'in',
            attrs: { label: { text: 'in端口11'}},
            args: { x: '0%', y: '30%' }
        },
        {
            group: 'in',
            attrs: { label: { text: 'in端口2'}}
        },
        {
            group: 'out',
            attrs: { label: { text: 'out端口1'}},
            args: { x: '100%', y: '20%' }
        },
        {
            group: 'out',
            attrs: { label: { text: 'out端口2'}}
        }
    ])
    rectModelTwo.addTo(graph.value)
}

// 创建两个自动链接的rect元素
function createAutoLinkRect() {
    const rectAutoLinkModel = new shapes.standard.Rectangle({
        position: { x: 100, y: 300 },
        size: { width: 90, height: 90 },
        attrs: {
            body: { fill: '#8ECAE6' },
            label: {
                text: '端口模块1',
                fontSize: 16,
                textAnchor: 'middle'
            }
        },
        ports: {
            groups: {
                out: portDataRight
            }
        }
    })
    // 添加多个端口
    rectAutoLinkModel.addPorts([
        {
            group: 'out',
            id: '1',
            attrs: { text: { label: '端口1' }}
        },
        {
            group: 'out',
            id: '2',
            attrs: { text: { label: '端口2' }}
        }
    ])
    rectAutoLinkModel.addTo(graph.value)

    // 获取元素所有端口
    const findElementPorts = rectAutoLinkModel.getPorts()

    // 创建第二个rect元素
    const rectAutoLinkModelTwo = new shapes.standard.Rectangle({
        position: { x: 400,  y: 300 },
        size: { width: 90, height: 90 },
        attrs: {
            body: { fill: '#8ECAE6' },
            label: {
                text: '端口模块2',
                fontSize: 16,
                textAnchor: 'middle',
                y: 0,
                x: 0
            }
        },
        ports: {
            groups: {
                in: portsIn,
                out: portsOut
            }
        }
    })
    rectAutoLinkModelTwo.addPorts([
        {
            group: 'in',
            id: '1',
            attrs: { label: { text: 'in端口1'}}
        },
        {
            group: 'in',
            attrs: { label: { text: 'in端口2'}}
        },
        {
            group: 'out',
            attrs: { label: { text: 'out端口1'}}
        },
        {
            group: 'out',
            attrs: { label: { text: 'out端口2'}}
        }
    ])
    rectAutoLinkModelTwo.addTo(graph.value)
    const findElementPortsTwo = rectAutoLinkModelTwo.getPorts()
    // console.log(findElementPortsTwo[0], findElementPorts[0], 2222);

    // 创建连线
    let Links = new shapes.standard.Link({
        // smooth: true, // 连接器使用三次贝塞尔曲线插值路径点
        // source: {
        //     id: findElementPorts[0].id,
        // },
        // target: {
        //     id: findElementPortsTwo[0].id,
        // },
        attrs: {
            line: {
                stroke: "#aaa",
                strokeWidth: 1,
            }
        },
    });
    Links.source(findElementPorts[0].id)
    Links.target(findElementPortsTwo[0].id)
    Links.addTo(graph.value)
}

// Actions
function appendMessage(p) {
    var body = document.getElementById('paper-links-message');

    // Remove paragraph from DOM if it already exists
    body.innerHTML = '';

    body.appendChild(p);
}

function showLinkTools(linkView) {  
    var tools = new dia.ToolsView({
        tools: [
            new linkTools.Remove({
                distance: '50%',
                markup: [{
                    tagName: 'circle',
                    selector: 'button',
                    attributes: {
                        'r': 7,
                        'fill': '#f6f6f6',
                        'stroke': '#ff5148',
                        'stroke-width': 2,
                        'cursor': 'pointer'
                    }
                }, {
                    tagName: 'path',
                    selector: 'icon',
                    attributes: {
                        'd': 'M -3 -3 3 3 M -3 3 3 -3',
                        'fill': 'none',
                        'stroke': '#ff5148',
                        'stroke-width': 2,
                        'pointer-events': 'none'
                    }
                }]
            })
        ]
    });
    linkView.addTools(tools);
}

nextTick(() => {
    createGraph();
    createRect();
    createAutoLinkRect()
});
</script>

<style lang="scss" src="./style.scss"></style>
